import { NextRequest } from 'next/server';
import { withMiddleware } from '@/lib/middleware/entry';
import { errorResponse, successResponse, optionsResponse } from '@/lib/response';

function extractTitle(html: string): string {
  const og = html.match(/<meta[^>]+property=["']og:title["'][^>]+content=["']([^"']+)["']/i);
  if (og) return og[1];
  const tw = html.match(/<meta[^>]+name=["']twitter:title["'][^>]+content=["']([^"']+)["']/i);
  if (tw) return tw[1];
  const t = html.match(/<title\s*>\s*([^<]+)\s*<\/title>/i);
  return t ? t[1] : '';
}

function extractDescription(html: string): string {
  const og = html.match(/<meta[^>]+property=["']og:description["'][^>]+content=["']([^"']+)["']/i);
  if (og) return og[1];
  const tw = html.match(/<meta[^>]+name=["']twitter:description["'][^>]+content=["']([^"']+)["']/i);
  if (tw) return tw[1];
  const meta = html.match(/<meta[^>]+name=["']description["'][^>]+content=["']([^"']+)["']/i);
  return meta ? meta[1] : '';
}

function extractIcon(html: string): string | undefined {
  const icon = html.match(/<link[^>]+rel=["']icon["'][^>]+href=["']([^"']+)["']/i);
  if (icon) return icon[1];
  const shortcut = html.match(/<link[^>]+rel=["']shortcut icon["'][^>]+href=["']([^"']+)["']/i);
  if (shortcut) return shortcut[1];
  const apple = html.match(/<link[^>]+rel=["']apple-touch-icon(?:-precomposed)?["'][^>]+href=["']([^"']+)["']/i);
  if (apple) return apple[1];
  return undefined;
}

function decodeHTMLEntities(text: string): string {
  const entities: Record<string, string> = {
    '&amp;': '&',
    '&lt;': '<',
    '&gt;': '>',
    '&quot;': '"',
    '&#39;': "'",
    '&apos;': "'",
    '&nbsp;': ' ',
    '&mdash;': '—',
    '&ndash;': '–',
    '&copy;': '©',
    '&reg;': '®'
  };
  text = text.replace(/&(amp|lt|gt|quot|apos|nbsp|mdash|ndash|copy|reg);/g, (m) => entities[m] || m);
  text = text.replace(/&#(\d+);/g, (_, code) => String.fromCharCode(parseInt(code, 10)));
  text = text.replace(/&#x([\da-fA-F]+);/g, (_, code) => String.fromCharCode(parseInt(code, 16)));
  return text;
}

function extractText(html: string): string {
  let s = html
    .replace(/<script[\s\S]*?<\/script>/gi, '')
    .replace(/<style[\s\S]*?<\/style>/gi, '')
    .replace(/<noscript[\s\S]*?<\/noscript>/gi, '')
    .replace(/<!--[\s\S]*?-->/g, '');

  const blocks = [
    'p','div','section','article','header','footer','aside','main','nav',
    'h1','h2','h3','h4','h5','h6','pre','blockquote','table','tr','td','th',
    'thead','tbody','figure','figcaption','address','ul','ol','li'
  ];
  for (const tag of blocks) {
    const open = new RegExp(`<${tag}[^>]*>`, 'gi');
    const close = new RegExp(`</${tag}>`, 'gi');
    s = s.replace(open, '\n').replace(close, '\n');
  }
  s = s.replace(/<br\s*\/?\s*>/gi, '\n');
  s = s.replace(/<\/?[^>]+>/g, '');

  s = decodeHTMLEntities(s)
    .replace(/\r/g, '')
    .replace(/\t/g, ' ')
    .replace(/\u00A0/g, ' ')
    .replace(/[ \t]{2,}/g, ' ')
    .replace(/\n{3,}/g, '\n\n')
    .trim();

  return s;
}

async function handler(req: NextRequest) {
  let body: any;
  try {
    body = await req.json();
  } catch {
    return errorResponse('请求体需为 JSON', 400);
  }

  const { url } = body;
  if (!url || typeof url !== 'string' || !url.startsWith('http')) {
    return errorResponse('缺少有效的 URL', 400);
  }

  try { 
    const response = await fetch(url, {
      redirect: 'follow',
      headers: {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0 Safari/537.36',
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
        'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8'
      }
    });
    if (!response.ok) {
      return errorResponse(`抓取失败: ${response.status}`, 500);
    }
    const html = await response.text();

    const title = extractTitle(html);
    let description = extractDescription(html);
    let iconUrl = extractIcon(html) || '';

    // 处理相对路径，使用页面 URL 作为基准
    if (iconUrl && !/^https?:\/\//i.test(iconUrl)) {
      iconUrl = new URL(iconUrl, url).href;
    }

    // 若未找到图标，回退到 /favicon.ico
    if (!iconUrl) {
      const base = new URL(url);
      iconUrl = new URL('/favicon.ico', base.origin).href;
    }

    // 仅返回纯文本内容
    const bodyMatch = html.match(/<body[^>]*>([\s\S]*?)<\/body>/i);
    // 去掉style标签
    const noStyleHtml = bodyMatch ? bodyMatch[1].replace(/<style[\s\S]*?<\/style>/gi, '') : html;
    const textContent = extractText(noStyleHtml);

    // 若描述为空，使用正文前 180 字作为摘要
    if (!description || description.trim() === '') {
      description = textContent.slice(0, 180).replace(/\s+/g, ' ').trim();
    }

    // 若正文为空，至少返回标题或描述，避免全空
    const finalContent = textContent.trim() !== '' ? textContent : (description || title || '');
    // 终态清洗，确保绝对没有标签残留
    const sanitizedContent = finalContent
      .replace(/<script[\s\S]*?<\/script>/gi, '')
      .replace(/<style[\s\S]*?<\/style>/gi, '')
      .replace(/<\/?[^>]+>/g, '')
      .replace(/[ \t]{2,}/g, ' ')
      .replace(/\n{3,}/g, '\n\n')
      .trim();

    // 去除链接（URL、www、mailto、tel）
    const noLinkContent = sanitizedContent
      .replace(/\bhttps?:\/\/[^\s]+/gi, '')
      .replace(/\bwww\.[^\s]+/gi, '')
      .replace(/\bmailto:[^\s]+/gi, '')
      .replace(/\btel:[^\s]+/gi, '')
      .replace(/\((?:https?:\/\/|www\.)[^\)]*\)/gi, '')
      .replace(/[ \t]{2,}/g, ' ')
      .replace(/\n{3,}/g, '\n\n')
      .trim();
    
    return successResponse({
      title,
      description,
      content: noLinkContent,
      iconUrl
    });
  } catch (e: any) {
    console.error('抓取或解析失败:', e);
    return errorResponse(`处理失败: ${e.message}`, 500);
  }
}

export const POST = withMiddleware(handler);
export async function OPTIONS() { return optionsResponse(); }